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
|
extdll.inc
|
||||||
""")
|
""")
|
||||||
|
|
||||||
Import('env plugin_env')
|
Import('env plugin_env plugin_uenv')
|
||||||
|
|
||||||
# build library
|
# build library
|
||||||
|
# in Unicode compilation, we should really build both variants but I can't get it to work [Wizou]
|
||||||
api_env = env.Clone()
|
if env['UNICODE']:
|
||||||
api_env.Append(CPPPATH = ['#Source/exehead'])
|
api_uenv = plugin_uenv.Clone()
|
||||||
lib = api_env.Library(lib_target, lib_files)
|
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
|
# distribute library, files and examples
|
||||||
|
|
||||||
env.DistributeExamples(api_files, path='Plugin/nsis')
|
env.DistributeExamples(api_files, path='Plugin/nsis')
|
||||||
|
|
||||||
if env['PLATFORM'] == 'win32':
|
if env['PLATFORM'] == 'win32':
|
||||||
|
if env['UNICODE']:
|
||||||
|
env.DistributeExamples(libW, lib_target+".lib", path='Plugin/nsis')
|
||||||
env.DistributeExamples(lib, path='Plugin/nsis')
|
env.DistributeExamples(lib, path='Plugin/nsis')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -57,3 +65,6 @@ env.Install('#$BUILD_PREFIX/api/nsis', api_files + lib)
|
||||||
plugin_env.Append(CPPPATH = ['#$BUILD_PREFIX/api'])
|
plugin_env.Append(CPPPATH = ['#$BUILD_PREFIX/api'])
|
||||||
plugin_env.Append(LIBPATH = ['#$BUILD_PREFIX/api/nsis'])
|
plugin_env.Append(LIBPATH = ['#$BUILD_PREFIX/api/nsis'])
|
||||||
plugin_env.Append(LIBS = [lib_target])
|
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
|
InitPluginsDir
|
||||||
File "/oname=$PLUGINSDIR\${FILE}" "${FILE}"
|
File "/oname=$PLUGINSDIR\${FILE}" "${FILE}"
|
||||||
!ifdef NSIS_UNICODE
|
!ifdef NSIS_UNICODE
|
||||||
InstallOptions::make_unicode "$PLUGINSDIR\${FILE}"
|
InstallOptionsW::make_unicode "$PLUGINSDIR\${FILE}"
|
||||||
!endif
|
!endif
|
||||||
!insertmacro INSTALLOPTIONS_WRITE "${FILE}" "Settings" "RTL" "$(^RTL)"
|
!insertmacro INSTALLOPTIONS_WRITE "${FILE}" "Settings" "RTL" "$(^RTL)"
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ Macros and conversion functions for InstallOptions
|
||||||
InitPluginsDir
|
InitPluginsDir
|
||||||
File "/oname=$PLUGINSDIR\${FILENAME}" "${FILE}"
|
File "/oname=$PLUGINSDIR\${FILENAME}" "${FILE}"
|
||||||
!ifdef NSIS_UNICODE
|
!ifdef NSIS_UNICODE
|
||||||
InstallOptions::make_unicode "$PLUGINSDIR\${FILENAME}"
|
InstallOptionsW::make_unicode "$PLUGINSDIR\${FILENAME}"
|
||||||
!endif
|
!endif
|
||||||
!insertmacro INSTALLOPTIONS_WRITE "${FILENAME}" "Settings" "RTL" "$(^RTL)"
|
!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) {
|
DWORD WINAPI MakeNSISProc(LPVOID p) {
|
||||||
|
#ifdef _UNICODE
|
||||||
TCHAR buf[1024];
|
TCHAR buf[1024];
|
||||||
|
#endif
|
||||||
char iobuf[1024]; //i/o buffer
|
char iobuf[1024]; //i/o buffer
|
||||||
STARTUPINFO si={sizeof(si),};
|
STARTUPINFO si={sizeof(si),};
|
||||||
SECURITY_ATTRIBUTES sa={sizeof(sa),};
|
SECURITY_ATTRIBUTES sa={sizeof(sa),};
|
||||||
|
|
|
@ -53,4 +53,4 @@ test_env.Append(CPPPATH = ['#$BUILD_CONFIG'])
|
||||||
|
|
||||||
# return
|
# 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
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
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'])
|
defenv.Append(LINKFLAGS = ['/debug'])
|
||||||
|
|
||||||
### unicode
|
### unicode
|
||||||
if defenv['UNICODE']:
|
tdefenv = defenv.Clone()
|
||||||
defenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE'])
|
if tdefenv['UNICODE']:
|
||||||
|
tdefenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE'])
|
||||||
|
|
||||||
### workarounds
|
### workarounds
|
||||||
|
|
||||||
|
@ -101,19 +102,19 @@ stub_env.Append(CCFLAGS = ['/W3']) # level 3 warnings
|
||||||
|
|
||||||
stub_env.Append(LINKFLAGS = ['/opt:nowin98']) # 512 bytes align
|
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 = ['$NODEFLIBS_FLAG']) # no default libraries
|
||||||
stub_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file
|
stub_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file
|
||||||
stub_env.Append(CCFLAGS = ['/FAcs']) # full listing files
|
stub_env.Append(CCFLAGS = ['/FAcs']) # full listing files
|
||||||
stub_env.Append(CCFLAGS = ['/Fa${TARGET}.lst']) # listing file name
|
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 environment
|
||||||
|
|
||||||
makensis_env = defenv.Clone()
|
makensis_env = tdefenv.Clone()
|
||||||
|
|
||||||
makensis_env.Append(CPPPATH = ['#$BUILD_CONFIG'])
|
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 = ['/opt:nowin98']) # 512 bytes align
|
||||||
plugin_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file
|
plugin_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file
|
||||||
|
|
||||||
|
plugin_uenv = plugin_env.Clone()
|
||||||
|
plugin_uenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE'])
|
||||||
|
|
||||||
### util environment
|
### util environment
|
||||||
|
|
||||||
util_env = defenv.Clone()
|
util_env = tdefenv.Clone()
|
||||||
|
|
||||||
if not defenv['DEBUG']:
|
if not defenv['DEBUG']:
|
||||||
util_env.Append(CCFLAGS = ['/O1']) # optimize for speed
|
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):
|
def add_file(file):
|
||||||
file = File(file)
|
file = File(file)
|
||||||
add_file_to_emitter(stub_env, 'PROGEMITTER', 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(util_env, 'PROGEMITTER', file)
|
||||||
add_file_to_emitter(plugin_env, 'SHLIBEMITTER', 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.
|
# MSVC 6 SP6 doesn't like direct shifting of 64-bit integers.
|
||||||
|
@ -240,6 +246,7 @@ else:
|
||||||
|
|
||||||
if not conf.TryLink(int64test, '.c'):
|
if not conf.TryLink(int64test, '.c'):
|
||||||
stub_env.Append(CPPDEFINES = ['_NSIS_NO_INT64_SHR'])
|
stub_env.Append(CPPDEFINES = ['_NSIS_NO_INT64_SHR'])
|
||||||
|
stub_uenv.Append(CPPDEFINES = ['_NSIS_NO_INT64_SHR'])
|
||||||
|
|
||||||
conf.Finish()
|
conf.Finish()
|
||||||
|
|
||||||
|
@ -256,4 +263,4 @@ conf.Finish()
|
||||||
|
|
||||||
### return
|
### 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]
|
util_env = envs[3]
|
||||||
cp_util_env = envs[4]
|
cp_util_env = envs[4]
|
||||||
test_env = envs[5]
|
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 ###
|
####### Distribution ###
|
||||||
|
@ -484,12 +486,17 @@ defenv.DistributeConf('nsisconf.nsh')
|
||||||
####### Stubs ###
|
####### Stubs ###
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def BuildStub(compression, solid):
|
def BuildStub(compression, solid, unicode):
|
||||||
env = stub_env.Clone()
|
|
||||||
|
|
||||||
suffix = ''
|
suffix = ''
|
||||||
if solid:
|
if solid:
|
||||||
suffix = '_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)
|
build_dir = '$BUILD_PREFIX/stub_%s%s' % (compression, suffix)
|
||||||
|
|
||||||
|
@ -507,8 +514,12 @@ for stub in stubs:
|
||||||
if stub in defenv['SKIPSTUBS']:
|
if stub in defenv['SKIPSTUBS']:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
BuildStub(stub, False)
|
if defenv['UNICODE']:
|
||||||
BuildStub(stub, True)
|
BuildStub(stub, False, True)
|
||||||
|
BuildStub(stub, True, True)
|
||||||
|
|
||||||
|
BuildStub(stub, False, False)
|
||||||
|
BuildStub(stub, True, False)
|
||||||
|
|
||||||
defenv.DistributeStubs('Source/exehead/uninst.ico',names='uninst')
|
defenv.DistributeStubs('Source/exehead/uninst.ico',names='uninst')
|
||||||
|
|
||||||
|
@ -569,11 +580,25 @@ def DistributeExtras(env, target, examples, docs):
|
||||||
####### Plug-ins ###
|
####### 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,
|
entry = 'DllMain', res = None, resources = None,
|
||||||
defines = None, flags = None, nodeflib = True,
|
defines = None, flags = None, nodeflib = True,
|
||||||
cppused = False):
|
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']:
|
if cppused and env['CPP_REQUIRES_STDLIB']:
|
||||||
nodeflib = False
|
nodeflib = False
|
||||||
|
@ -595,7 +620,10 @@ def BuildPlugin(target, source, libs, examples = None, docs = None,
|
||||||
plugin = i
|
plugin = i
|
||||||
break
|
break
|
||||||
env.DistributePlugin(plugin)
|
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)
|
DistributeExtras(env, target, examples, docs)
|
||||||
|
|
||||||
for plugin in plugin_libs + plugins:
|
for plugin in plugin_libs + plugins:
|
||||||
|
@ -604,8 +632,10 @@ for plugin in plugin_libs + plugins:
|
||||||
|
|
||||||
path = 'Contrib/' + plugin
|
path = 'Contrib/' + plugin
|
||||||
build_dir = '$BUILD_PREFIX/' + 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)
|
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
|
// Construction/Destruction
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
CDialogTemplate::CDialogTemplate(BYTE* pbData, unsigned int uCodePage) {
|
CDialogTemplate::CDialogTemplate(BYTE* pbData, bool build_unicode, unsigned int uCodePage) {
|
||||||
m_uCodePage = uCodePage;
|
m_uCodePage = uCodePage;
|
||||||
|
m_build_unicode = build_unicode;
|
||||||
|
|
||||||
m_dwHelpId = 0;
|
m_dwHelpId = 0;
|
||||||
m_szClass = 0;
|
m_szClass = 0;
|
||||||
|
@ -598,7 +599,7 @@ BYTE* CDialogTemplate::Save(DWORD& dwSize) {
|
||||||
// Write class variant length array
|
// Write class variant length array
|
||||||
WCHAR *szClass = m_vItems[i]->szClass;
|
WCHAR *szClass = m_vItems[i]->szClass;
|
||||||
#ifdef _UNICODE
|
#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
|
szClass = L"RichEdit20W"; // transmute ANSI RichEdit control into Unicode RichEdit
|
||||||
#endif
|
#endif
|
||||||
WriteStringOrId(szClass);
|
WriteStringOrId(szClass);
|
||||||
|
|
|
@ -107,7 +107,7 @@ typedef struct {
|
||||||
|
|
||||||
class CDialogTemplate {
|
class CDialogTemplate {
|
||||||
public:
|
public:
|
||||||
CDialogTemplate(BYTE* pbData, unsigned int uCodePage=CP_ACP);
|
CDialogTemplate(BYTE* pbData, bool build_unicode, unsigned int uCodePage=CP_ACP);
|
||||||
virtual ~CDialogTemplate();
|
virtual ~CDialogTemplate();
|
||||||
|
|
||||||
short GetWidth();
|
short GetWidth();
|
||||||
|
@ -136,6 +136,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_bExtended;
|
bool m_bExtended;
|
||||||
|
bool m_build_unicode;
|
||||||
|
|
||||||
DWORD m_dwHelpId; // Extended only
|
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();
|
for (dir_reader::iterator files_itr = dr->files().begin();
|
||||||
files_itr != dr->files().end();
|
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")))
|
if (!dir_reader::matches(*files_itr, _T("*.dll")))
|
||||||
continue;
|
continue;
|
||||||
|
@ -109,7 +109,10 @@ void Plugins::GetExports(const tstring &pathToDll, bool displayInfo)
|
||||||
return;
|
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);
|
FIX_ENDIAN_INT16_INPLACE(NTHeaders->FileHeader.Characteristics);
|
||||||
if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
|
if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
|
||||||
|
@ -143,6 +146,12 @@ void Plugins::GetExports(const tstring &pathToDll, bool displayInfo)
|
||||||
const tstring lcsig = lowercase(signature);
|
const tstring lcsig = lowercase(signature);
|
||||||
m_command_to_path[lcsig] = pathToDll;
|
m_command_to_path[lcsig] = pathToDll;
|
||||||
m_command_lowercase_to_command[lcsig] = signature;
|
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)
|
if (displayInfo)
|
||||||
_ftprintf(g_output, _T(" - %s\n"), signature.c_str());
|
_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));
|
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 {
|
int Plugins::GetPluginHandle(bool uninst, const tstring& command) const {
|
||||||
if (uninst) {
|
if (uninst) {
|
||||||
return get_value(m_command_to_uninstall_data_handle, command, -1);
|
return get_value(m_command_to_uninstall_data_handle, command, -1);
|
||||||
|
|
|
@ -30,6 +30,7 @@ class Plugins
|
||||||
tstring NormalizedCommand(const tstring& command) const;
|
tstring NormalizedCommand(const tstring& command) const;
|
||||||
int GetPluginHandle(bool uninst, const tstring& command) const;
|
int GetPluginHandle(bool uninst, const tstring& command) const;
|
||||||
tstring GetPluginPath(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);
|
void SetDllDataHandle(bool uninst, const tstring& command, int dataHandle);
|
||||||
|
|
||||||
private: // methods
|
private: // methods
|
||||||
|
@ -38,6 +39,7 @@ class Plugins
|
||||||
private: // data members
|
private: // data members
|
||||||
std::map<tstring, tstring> m_command_lowercase_to_command;
|
std::map<tstring, tstring> m_command_lowercase_to_command;
|
||||||
std::map<tstring, tstring> m_command_to_path;
|
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_data_handle;
|
||||||
std::map<tstring, int> m_command_to_uninstall_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);
|
definedlist.add(_T("NSIS_VERSION"), NSIS_VERSION);
|
||||||
|
|
||||||
#ifdef _UNICODE
|
build_unicode=false;
|
||||||
definedlist.add(_T("NSIS_UNICODE"));
|
definedlist.add(_T("NSIS_CHAR_SIZE"), _T("1")); // this can change after a UnicodeInstaller instruction is found
|
||||||
definedlist.add(_T("NSIS_CHAR_SIZE"), _T("2"));
|
|
||||||
#else
|
|
||||||
definedlist.add(_T("NSIS_CHAR_SIZE"), _T("1"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// automatically generated header file containing all defines
|
// automatically generated header file containing all defines
|
||||||
#include <nsis-defines.h>
|
#include <nsis-defines.h>
|
||||||
|
@ -230,8 +226,8 @@ CEXEBuild::CEXEBuild() :
|
||||||
|
|
||||||
uninstaller_writes_used=0;
|
uninstaller_writes_used=0;
|
||||||
|
|
||||||
build_strlist.add(_T(""),0);
|
build_strlist.add(_T(""), CP_ACP, false, build_unicode);
|
||||||
ubuild_strlist.add(_T(""),0);
|
ubuild_strlist.add(_T(""), CP_ACP, false, build_unicode);
|
||||||
|
|
||||||
build_langstring_num=0;
|
build_langstring_num=0;
|
||||||
ubuild_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 (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];
|
TCHAR buf[NSIS_MAX_STRLEN*4];
|
||||||
preprocess_string(buf,string,codepage);
|
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
|
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);
|
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
|
// based on Dave Laundon's code
|
||||||
int CEXEBuild::preprocess_string(TCHAR *out, const TCHAR *in, WORD codepage/*=CP_ACP*/)
|
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
|
else
|
||||||
{
|
{
|
||||||
// normal string
|
// 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);
|
if (x) wsprintf(fname,_T("%s section \"%s\" (%d)"),str,section_name,cnt);
|
||||||
else wsprintf(fname,_T("unnamed %s section (%d)"),str,cnt);
|
else wsprintf(fname,_T("unnamed %s section (%d)"),str,cnt);
|
||||||
|
@ -2080,7 +2105,7 @@ again:
|
||||||
#define REMOVE_ICON(id) if (disable_window_icon) { \
|
#define REMOVE_ICON(id) if (disable_window_icon) { \
|
||||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, id, NSIS_DEFAULT_LANG); \
|
BYTE* dlg = res_editor->GetResource(RT_DIALOG, id, NSIS_DEFAULT_LANG); \
|
||||||
if (dlg) { \
|
if (dlg) { \
|
||||||
CDialogTemplate dt(dlg,uDefCodePage); \
|
CDialogTemplate dt(dlg,build_unicode,uDefCodePage); \
|
||||||
res_editor->FreeResource(dlg); \
|
res_editor->FreeResource(dlg); \
|
||||||
if (dt.RemoveItem(IDC_ULICON)) { \
|
if (dt.RemoveItem(IDC_ULICON)) { \
|
||||||
DialogItemTemplate* text = dt.GetItem(IDC_INTROTEXT); \
|
DialogItemTemplate* text = dt.GetItem(IDC_INTROTEXT); \
|
||||||
|
@ -2210,7 +2235,7 @@ void CEXEBuild::AddStandardStrings()
|
||||||
void CEXEBuild::PrepareHeaders(IGrowBuf *hdrbuf)
|
void CEXEBuild::PrepareHeaders(IGrowBuf *hdrbuf)
|
||||||
{
|
{
|
||||||
GrowBuf blocks_buf;
|
GrowBuf blocks_buf;
|
||||||
growbuf_writer_sink sink(&blocks_buf);
|
growbuf_writer_sink sink(&blocks_buf, build_unicode);
|
||||||
|
|
||||||
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
||||||
cur_header->blocks[NB_PAGES].offset = sizeof(header) + blocks_buf.getlen();
|
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);
|
entry_writer::write_block(cur_entries, &sink);
|
||||||
|
|
||||||
cur_header->blocks[NB_STRINGS].offset = sizeof(header) + blocks_buf.getlen();
|
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();
|
cur_header->blocks[NB_LANGTABLES].offset = sizeof(header) + blocks_buf.getlen();
|
||||||
lang_table_writer::write_block(cur_langtables, &sink, cur_header->langtable_size);
|
lang_table_writer::write_block(cur_langtables, &sink, cur_header->langtable_size);
|
||||||
|
@ -2244,7 +2274,7 @@ void CEXEBuild::PrepareHeaders(IGrowBuf *hdrbuf)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
growbuf_writer_sink sink2(hdrbuf);
|
growbuf_writer_sink sink2(hdrbuf, build_unicode);
|
||||||
header_writer header(&sink2);
|
header_writer header(&sink2);
|
||||||
header.write(cur_header);
|
header.write(cur_header);
|
||||||
|
|
||||||
|
@ -2259,7 +2289,8 @@ int CEXEBuild::SetVarsSection()
|
||||||
VerifyDeclaredUserVarRefs(&m_UserVarNames);
|
VerifyDeclaredUserVarRefs(&m_UserVarNames);
|
||||||
int MaxUserVars = m_UserVarNames.getnum();
|
int MaxUserVars = m_UserVarNames.getnum();
|
||||||
// -1 because the default size is 1
|
// -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));
|
ERROR_MSG(_T("Internal compiler error #12346: invalid exehead cannot find section \"%s\"!\n"), _T(NSIS_VARS_SECTION));
|
||||||
return PS_ERROR;
|
return PS_ERROR;
|
||||||
|
@ -2658,7 +2689,7 @@ int CEXEBuild::write_output(void)
|
||||||
int ne=build_header.blocks[NB_ENTRIES].num;
|
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));
|
INFO_MSG(_T("%d instruction%s (%d bytes), "),ne,ne==1?_T(""):_T("s"),ne*sizeof(entry));
|
||||||
int ns=build_strlist.getnum();
|
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;
|
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());
|
INFO_MSG(_T("%d language table%s (%d bytes).\n"),nlt,nlt==1?_T(""):_T("s"),build_langtables.getlen());
|
||||||
if (ubuild_entries.getlen())
|
if (ubuild_entries.getlen())
|
||||||
|
@ -2687,7 +2718,7 @@ int CEXEBuild::write_output(void)
|
||||||
ne=build_uninst.blocks[NB_ENTRIES].num;
|
ne=build_uninst.blocks[NB_ENTRIES].num;
|
||||||
INFO_MSG(_T("%d instruction%s (%d bytes), "),ne,ne==1?_T(""):_T("s"),ubuild_entries.getlen());
|
INFO_MSG(_T("%d instruction%s (%d bytes), "),ne,ne==1?_T(""):_T("s"),ubuild_entries.getlen());
|
||||||
ns=ubuild_strlist.getnum();
|
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;
|
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());
|
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;
|
MMapBuf udata;
|
||||||
|
|
||||||
{
|
{
|
||||||
growbuf_writer_sink sink(&udata);
|
growbuf_writer_sink sink(&udata, build_unicode);
|
||||||
firstheader_writer w(&sink);
|
firstheader_writer w(&sink);
|
||||||
w.write(&fh);
|
w.write(&fh);
|
||||||
}
|
}
|
||||||
|
@ -3532,12 +3563,40 @@ void CEXEBuild::VerifyDeclaredUserVarRefs(UserVarsStringList *pVarsStringList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CEXEBuild::set_compressor(const tstring& compressor, const bool solid) {
|
#ifdef _UNICODE
|
||||||
tstring stub = stubs_dir + PLATFORM_PATH_SEPARATOR_STR + compressor;
|
int CEXEBuild::set_build_unicode(bool unicode_installer)
|
||||||
if (solid)
|
{
|
||||||
stub += _T("_solid");
|
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*/) {
|
int CEXEBuild::update_exehead(const tstring& file, size_t *size/*=NULL*/) {
|
||||||
|
|
|
@ -136,7 +136,9 @@ class CEXEBuild {
|
||||||
int prepare_uninstaller();
|
int prepare_uninstaller();
|
||||||
int pack_exe_header();
|
int pack_exe_header();
|
||||||
|
|
||||||
|
int set_build_unicode(bool unicode_installer);
|
||||||
int set_compressor(const tstring& compressor, const bool solid);
|
int set_compressor(const tstring& compressor, const bool solid);
|
||||||
|
int load_stub();
|
||||||
int update_exehead(const tstring& file, size_t *size=NULL);
|
int update_exehead(const tstring& file, size_t *size=NULL);
|
||||||
void update_exehead(const unsigned char *new_exehead, size_t new_size);
|
void update_exehead(const unsigned char *new_exehead, size_t new_size);
|
||||||
|
|
||||||
|
@ -377,6 +379,7 @@ class CEXEBuild {
|
||||||
// a whole bunch O data.
|
// a whole bunch O data.
|
||||||
|
|
||||||
tstring stubs_dir;
|
tstring stubs_dir;
|
||||||
|
tstring stub_filename;
|
||||||
|
|
||||||
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
|
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
|
||||||
ICompressor *compressor;
|
ICompressor *compressor;
|
||||||
|
@ -392,6 +395,7 @@ class CEXEBuild {
|
||||||
int build_compress_dict_size;
|
int build_compress_dict_size;
|
||||||
|
|
||||||
bool no_space_texts;
|
bool no_space_texts;
|
||||||
|
bool build_unicode;
|
||||||
|
|
||||||
bool has_called_write_output;
|
bool has_called_write_output;
|
||||||
|
|
||||||
|
@ -442,7 +446,7 @@ class CEXEBuild {
|
||||||
GrowBuf build_instruction_entry_map,ubuild_instruction_entry_map, *cur_instruction_entry_map;
|
GrowBuf build_instruction_entry_map,ubuild_instruction_entry_map, *cur_instruction_entry_map;
|
||||||
TinyGrowBuf build_functions, ubuild_functions, *cur_functions;
|
TinyGrowBuf build_functions, ubuild_functions, *cur_functions;
|
||||||
TinyGrowBuf build_labels, ubuild_labels, *cur_labels;
|
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;
|
GrowBuf build_langtables, ubuild_langtables, *cur_langtables;
|
||||||
TinyGrowBuf build_pages, ubuild_pages, *cur_pages;
|
TinyGrowBuf build_pages, ubuild_pages, *cur_pages;
|
||||||
TinyGrowBuf build_ctlcolors, ubuild_ctlcolors, *cur_ctlcolors;
|
TinyGrowBuf build_ctlcolors, ubuild_ctlcolors, *cur_ctlcolors;
|
||||||
|
|
|
@ -722,7 +722,7 @@ DWORD CALLBACK StreamLicense(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#ifdef _UNICODE
|
#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)
|
DWORD CALLBACK StreamLicenseRTF(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
|
||||||
{
|
{
|
||||||
size_t len = lstrlen(((LPWSTR) dwCookie)+dwRead);
|
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
|
// We are doing this to store an integer value into a char string and we
|
||||||
// don't want false end of string values
|
// 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 CODE_SHORT(x) (WORD)((((WORD)(x) & 0x7F) | (((WORD)(x) & 0x3F80) << 1) | 0x8080))
|
||||||
#define MAX_CODED 0x3FFF
|
#define MAX_CODED 0x3FFF
|
||||||
// This macro takes a pointer to CHAR
|
// This macro takes a pointer to CHAR
|
||||||
#define DECODE_SHORT(c) (((c[1] & 0x7F) << 7) | (c[0] & 0x7F))
|
#define DECODE_SHORT(c) (((((char*)c)[1] & 0x7F) << 7) | (((char*)c)[0] & 0x7F))
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NSIS_INSTDIR_INVALID 1
|
#define NSIS_INSTDIR_INVALID 1
|
||||||
#define NSIS_INSTDIR_NOT_ENOUGH_SPACE 2
|
#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;
|
return table->nlf.m_szName;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// If the language table does not exist, then we default to Unicode in the
|
// If the language table does not exist, then we default to Unicode or ANSI
|
||||||
// Unicode version and English in the ANSI version.
|
// depending on the target installer type
|
||||||
#ifdef _UNICODE
|
|
||||||
if (codepage)
|
if (codepage)
|
||||||
*codepage = 1200; // Unicode
|
*codepage = build_unicode ? 1200 : 1252; // Unicode or CP1252
|
||||||
#else
|
|
||||||
if (codepage)
|
|
||||||
*codepage = 1252; // ANSI CP1252
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (lang == 1033)
|
if (lang == 1033)
|
||||||
return _T("English");
|
return _T("English");
|
||||||
|
@ -703,7 +698,7 @@ int CEXEBuild::GenerateLangTables() {
|
||||||
#define ADD_FONT(id) { \
|
#define ADD_FONT(id) { \
|
||||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, id, NSIS_DEFAULT_LANG); \
|
BYTE* dlg = res_editor->GetResource(RT_DIALOG, id, NSIS_DEFAULT_LANG); \
|
||||||
if (dlg) { \
|
if (dlg) { \
|
||||||
CDialogTemplate td(dlg); \
|
CDialogTemplate td(dlg,build_unicode); \
|
||||||
res_editor->FreeResource(dlg); \
|
res_editor->FreeResource(dlg); \
|
||||||
td.SetFont(build_font, (WORD) build_font_size); \
|
td.SetFont(build_font, (WORD) build_font_size); \
|
||||||
DWORD dwSize; \
|
DWORD dwSize; \
|
||||||
|
@ -758,7 +753,7 @@ int CEXEBuild::GenerateLangTables() {
|
||||||
#define ADD_FONT(id) { \
|
#define ADD_FONT(id) { \
|
||||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, id, NSIS_DEFAULT_LANG); \
|
BYTE* dlg = res_editor->GetResource(RT_DIALOG, id, NSIS_DEFAULT_LANG); \
|
||||||
if (dlg) { \
|
if (dlg) { \
|
||||||
CDialogTemplate td(dlg,lt[i].nlf.m_uCodePage); \
|
CDialogTemplate td(dlg,build_unicode,lt[i].nlf.m_uCodePage); \
|
||||||
res_editor->FreeResource(dlg); \
|
res_editor->FreeResource(dlg); \
|
||||||
if (font) td.SetFont(font, (WORD) lt[i].nlf.m_iFontSize); \
|
if (font) td.SetFont(font, (WORD) lt[i].nlf.m_iFontSize); \
|
||||||
if (lt[i].nlf.m_bRTL) { \
|
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)))
|
if (!memcmp(data+1,_T("{\\rtf"),5*sizeof(TCHAR)))
|
||||||
*data = SF_RTF;
|
*data = SF_RTF;
|
||||||
else
|
else if (unicode)
|
||||||
#ifdef _UNICODE
|
|
||||||
*data = SF_TEXT|SF_UNICODE;
|
*data = SF_TEXT|SF_UNICODE;
|
||||||
#else
|
else
|
||||||
*data = SF_TEXT;
|
*data = SF_TEXT;
|
||||||
#endif
|
|
||||||
return PS_OK;
|
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);
|
BYTE* dlg = res_editor->GetResource(RT_DIALOG, IDD_INSTFILES, NSIS_DEFAULT_LANG);
|
||||||
if (!dlg) throw runtime_error("IDD_INSTFILES doesn't exist!");
|
if (!dlg) throw runtime_error("IDD_INSTFILES doesn't exist!");
|
||||||
CDialogTemplate dt(dlg,uDefCodePage);
|
CDialogTemplate dt(dlg,build_unicode,uDefCodePage);
|
||||||
free(dlg);
|
free(dlg);
|
||||||
DialogItemTemplate* progress = dt.GetItem(IDC_PROGRESS);
|
DialogItemTemplate* progress = dt.GetItem(IDC_PROGRESS);
|
||||||
if (!progress) {
|
if (!progress) {
|
||||||
|
@ -2448,7 +2446,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
||||||
init_res_editor();
|
init_res_editor();
|
||||||
|
|
||||||
// Search for required items
|
// 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 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;
|
#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();
|
init_res_editor();
|
||||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG);
|
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);
|
res_editor->FreeResource(dlg);
|
||||||
|
|
||||||
|
@ -2687,6 +2685,25 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
||||||
}
|
}
|
||||||
return PS_OK;
|
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
|
// Ability to change compression methods from within the script
|
||||||
case TOK_SETCOMPRESSOR:
|
case TOK_SETCOMPRESSOR:
|
||||||
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
|
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
|
||||||
|
@ -3681,7 +3698,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
||||||
init_res_editor();
|
init_res_editor();
|
||||||
|
|
||||||
BYTE* dlg = res_editor->GetResource(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG);
|
BYTE* dlg = res_editor->GetResource(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG);
|
||||||
CDialogTemplate td(dlg,uDefCodePage);
|
CDialogTemplate td(dlg,build_unicode,uDefCodePage);
|
||||||
free(dlg);
|
free(dlg);
|
||||||
|
|
||||||
if (trim) {
|
if (trim) {
|
||||||
|
@ -5913,8 +5930,13 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
const tstring command = m_plugins.NormalizedCommand(line.gettoken_str(0));
|
tstring command = m_plugins.NormalizedCommand(line.gettoken_str(0));
|
||||||
const tstring dllPath = m_plugins.GetPluginPath(command);
|
#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);
|
int data_handle = m_plugins.GetPluginHandle(uninstall_mode?true:false, command);
|
||||||
|
|
||||||
if (uninstall_mode) uninst_plugin_used = true;
|
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
|
// DLL name on the user machine
|
||||||
TCHAR tempDLL[NSIS_MAX_STRLEN];
|
TCHAR tempDLL[NSIS_MAX_STRLEN];
|
||||||
tstring dllName = get_file_name(dllPath);
|
|
||||||
wsprintf(tempDLL, _T("$PLUGINSDIR\\%s"), dllName.c_str());
|
wsprintf(tempDLL, _T("$PLUGINSDIR\\%s"), dllName.c_str());
|
||||||
|
|
||||||
// Add the DLL to the installer
|
// Add the DLL to the installer
|
||||||
|
|
|
@ -18,6 +18,97 @@
|
||||||
|
|
||||||
#include "strlist.h"
|
#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 StringList::add(const TCHAR *str, int case_sensitive)
|
||||||
{
|
{
|
||||||
int a=find(str,case_sensitive);
|
int a=find(str,case_sensitive);
|
||||||
|
@ -103,15 +194,6 @@ int StringList::getnum() const
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TCHAR *StringList::get() const
|
|
||||||
{
|
|
||||||
return (const TCHAR*) m_gr.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
int StringList::getcount() const
|
|
||||||
{
|
|
||||||
return m_gr.getlen() / sizeof(TCHAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========
|
// ==========
|
||||||
// DefineList
|
// DefineList
|
||||||
|
|
|
@ -104,18 +104,43 @@ public:
|
||||||
* Get the buffer straight as a const TCHAR pointer. Very unwise to use.
|
* Get the buffer straight as a const TCHAR pointer. Very unwise to use.
|
||||||
* @return m_gr.m_s cast as a TCHAR*.
|
* @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).
|
* Get the buffer size (number of TCHARs).
|
||||||
* @return 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;
|
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
|
* 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
|
* 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_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_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},
|
{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_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_UNINSTCAPTION,_T("UninstallCaption"),1,0,_T("uninstaller_caption"),TP_GLOBAL},
|
||||||
{TOK_UNINSTICON,_T("UninstallIcon"),1,0,_T("icon_on_local_system.ico"),TP_GLOBAL},
|
{TOK_UNINSTICON,_T("UninstallIcon"),1,0,_T("icon_on_local_system.ico"),TP_GLOBAL},
|
||||||
|
|
|
@ -70,6 +70,9 @@ enum
|
||||||
TOK_DEFVAR,
|
TOK_DEFVAR,
|
||||||
TOK_VI_ADDKEY,
|
TOK_VI_ADDKEY,
|
||||||
TOK_VI_SETPRODUCTVERSION,
|
TOK_VI_SETPRODUCTVERSION,
|
||||||
|
#ifdef _UNICODE
|
||||||
|
TOK_UNICODEINSTALLER,
|
||||||
|
#endif
|
||||||
|
|
||||||
TOK_MISCBUTTONTEXT,
|
TOK_MISCBUTTONTEXT,
|
||||||
TOK_DETAILSBUTTONTEXT,
|
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)
|
void writer_sink::write_string(const TCHAR *s, size_t size)
|
||||||
{
|
{
|
||||||
#ifdef _UNICODE
|
#ifdef _UNICODE
|
||||||
bool strEnd = false;
|
if (m_build_unicode)
|
||||||
TCHAR ch;
|
|
||||||
for (; size ; size--)
|
|
||||||
{
|
{
|
||||||
if (!strEnd)
|
bool strEnd = false;
|
||||||
|
TCHAR ch;
|
||||||
|
for (; size ; size--)
|
||||||
{
|
{
|
||||||
ch = *s++;
|
if (!strEnd)
|
||||||
if (ch == _T('\0'))
|
{
|
||||||
strEnd = true;
|
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
|
#else
|
||||||
char *wb = new char[size];
|
char *wb = new char[size];
|
||||||
memset(wb, 0, size);
|
memset(wb, 0, size);
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
class writer_sink {
|
class writer_sink {
|
||||||
public:
|
public:
|
||||||
writer_sink() {}
|
writer_sink() : m_build_unicode(false) {}
|
||||||
virtual ~writer_sink() {}
|
virtual ~writer_sink() {}
|
||||||
|
|
||||||
virtual void write_byte(const unsigned char b);
|
virtual void write_byte(const unsigned char b);
|
||||||
|
@ -38,7 +38,8 @@ public:
|
||||||
virtual void write_growbuf(const IGrowBuf *b);
|
virtual void write_growbuf(const IGrowBuf *b);
|
||||||
|
|
||||||
virtual void write_data(const void *data, const size_t size) = 0;
|
virtual void write_data(const void *data, const size_t size) = 0;
|
||||||
|
protected:
|
||||||
|
bool m_build_unicode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class writer {
|
class writer {
|
||||||
|
@ -53,7 +54,7 @@ protected:
|
||||||
|
|
||||||
class growbuf_writer_sink : public writer_sink {
|
class growbuf_writer_sink : public writer_sink {
|
||||||
public:
|
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);
|
virtual void write_data(const void *data, const size_t size);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue